/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.saber.certificacao.beansjsf.semescopo;

import br.com.saber.certificacao.beansjsf.interfacebean.BeanJSFInterface;
import br.com.saber.certificacao.ejbs.stateless.interfaces.CertificacaoBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.ObjetivoCertificacaoBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.QuestaoBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.RolesBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.UsuarioBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.VersaoBeanLocal;
import br.com.saber.certificacao.enums.Linguagem;
import br.com.saber.certificacao.enums.Papeis;
import br.com.saber.certificacao.enums.TipoProva;
import br.com.saber.certificacao.enums.TipoQuestao;
import br.com.saber.certificacao.modelos.Certificacao;
import br.com.saber.certificacao.modelos.Resposta;
import br.com.saber.certificacao.modelos.Roles;
import br.com.saber.certificacao.modelos.Usuario;
import br.com.saber.certificacao.modelos.Versao;
import br.com.saber.certificacao.utils.UtilMetodos;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.NoneScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

/**
 *  Manager Beans sem escopo,
 *  Responsavel por retornar Listas de SelectItens para as páginas.
 * @author gbvbahia
 */
@ManagedBean(name = "selectItemManager", eager = true)
@NoneScoped
public class SelectItemManager implements BeanJSFInterface {

    @EJB
    private ObjetivoCertificacaoBeanLocal objetivoCertificacaoBean;
    @EJB
    private QuestaoBeanLocal questaoBean;
    @EJB
    private VersaoBeanLocal versaoBean;
    @EJB
    private CertificacaoBeanLocal certificacaoBean;
    @EJB
    private UsuarioBeanLocal usuarioBean;
    @EJB
    private RolesBeanLocal rolesBean;

    /** Creates a new instance of SelectItemManager */
    public SelectItemManager() {
    }

    //====================
    // Iniciadores
    //====================
    @Override
    @PreDestroy
    public void end() {
        Logger.getLogger(this.getClass().getName()).log(Level.INFO, "SelectItemManager.end() executado!");
    }

    @Override
    @PostConstruct
    public void init() {
        Logger.getLogger(this.getClass().getName()).log(Level.INFO, "SelectItemManager.init() executado!");
    }

    /**
     * Cria uma lista de SelectItens das Roles que o usuário passado como
     * parámetro tem acesso.
     * @param usuario
     * @return List SelectItem
     */
    public List<SelectItem> getRoles(Usuario usuario) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Roles role : rolesBean.getRolesParaLiberar(usuario)) {
            toReturn.add(new SelectItem(role, role.getPapel().toString()));
        }
        return toReturn;
    }

    /**
     * Retorna todos os usuários que são dentro do papel passado.
     * Lembrado que os papeis são definidos por hierarquia, um Administrador é um Coordenador,
     * um Coordenador é um Professor, um professor é um Aluno.
     * @return List SelectItem
     */
    public List<SelectItem> getCoordenadores() {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Usuario coordenador : usuarioBean.buscarUsuariosPapel(Papeis.COORDENADOR)) {
            toReturn.add(new SelectItem(coordenador, coordenador.getNomeSobreNomeLogin()));
        }
        return toReturn;
    }

    /**
     * Retorna uma lista de SelectItems com todas as certificações que
     * o usuário é responsável.
     * @param usuarioLogado
     * @return List de SelectItems
     */
    public List<SelectItem> getCertificacoes(Usuario usuarioLogado) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Certificacao certificacao : certificacaoBean.buscarCertificacoesPorCoordenador(getCoordenadorResponsavel(usuarioLogado))) {
            toReturn.add(new SelectItem(certificacao, certificacao.getNome()));
        }
        return toReturn;
    }

    /**
     * Utilize para carregar as certificações que o professor tem acesso
     * e retornar como um selectItem
     * @param professor
     * @return 
     */
    public List<SelectItem> getLazyCertificacoes(Usuario professor) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Certificacao certificacao : certificacaoBean.loadLazyCertificacoesDoProfessor(professor)) {
            toReturn.add(new SelectItem(certificacao, certificacao.getNome()));
        }
        return toReturn;
    }

    private Usuario getCoordenadorResponsavel(Usuario usuario) {
        if (usuario.getMaxRole().getPapel().getLevel() >= Papeis.COORDENADOR.getLevel()) {
            return usuario;
        }
        if (usuario.getUsuarioResponsavel() == null) {
            return usuario;
        } else {
            return getCoordenadorResponsavel(usuario.getUsuarioResponsavel());
        }
    }

    /**
     * Retorna todas as certificações cadastradas com a quantidade mínina
     * de questões solicitadas.
     * @return Lista de SelectItem com as certificações que possuem o minimo de questões cadastradas.
     */
    public List<SelectItem> getCertificacoes(int qutadeQuestoes) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Certificacao certificacao : certificacaoBean.buscarCertificacaoComQuantidadeQuestoes(qutadeQuestoes)) {
            toReturn.add(new SelectItem(certificacao, certificacao.getNome()));
        }
        return toReturn;
    }

    public List<SelectItem> getCertificacoes() {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Certificacao certificacao : certificacaoBean.buscarTodasCertificacoes()) {
            toReturn.add(new SelectItem(certificacao, certificacao.getNome()));
        }
        return toReturn;
    }

    /**
     * Retorna as versões que possuem a quantidade minima de questões solicitadas
     * e que seja da certificação passada.
     * @param qtdadeQuestoes minima da versão
     * @param certificacao filtro da versão
     * @return Lista de SelectItens
     */
    public List<SelectItem> getVersoes(int qtdadeQuestoes, Certificacao certificacao, boolean versaoMother) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Versao v : versaoBean.buscarVersoesComMinimoQuestoes(qtdadeQuestoes, certificacao, versaoMother)) {
            toReturn.add(new SelectItem(v, v.getNome()));
        }
        return toReturn;
    }

    /**
     * Retorna todas as versões que o usuario(professor) tem acesso
     * limitado a certificação passada, versões que não sejam da Certificação
     * passada são ignoradas.
     * @param usuarioLogado
     * @param certificacaoQuestao
     * @return List de SelectItem
     */
    public List<SelectItem> getVersoes(Usuario usuarioLogado, Certificacao certificacao) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        if (usuarioLogado.getMaxRole().getPapel().equals(Papeis.PROFESSOR)) {
            for (Versao ver : versaoBean.buscarVersaoPorProfessorCertificacao(usuarioLogado, certificacao)) {
                toReturn.add(new SelectItem(ver, ver.versaoLabel()));
            }
        } else {
            for (Versao ver : versaoBean.buscarVersaoPorProfessorCertificacao(getCoordenadorResponsavel(usuarioLogado), certificacao)) {
                toReturn.add(new SelectItem(ver, ver.versaoLabel()));
            }
        }
        return toReturn;
    }

    /**
     * Retorna todas as versões que o usuario(professor) tem acesso
     * limitado a certificação passada, versões que não sejam da Certificação
     * passada são ignoradas. isMother filtra versão superior ou normal
     * @param usuarioLogado
     * @param certificacao
     * @param isMother
     * @return List de SelectItem
     */
    public List<SelectItem> getVersoes(Usuario usuarioLogado, Certificacao certificacao, boolean isMother) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        if (usuarioLogado.getMaxRole().getPapel().equals(Papeis.PROFESSOR)) {
            for (Versao ver : versaoBean.buscarVersaoPorProfessorCertificacao((usuarioLogado), certificacao, isMother)) {
                toReturn.add(new SelectItem(ver, ver.versaoLabel()));
            }
        } else {
            for (Versao ver : versaoBean.buscarVersaoPorProfessorCertificacao(getCoordenadorResponsavel(usuarioLogado), certificacao, isMother)) {
                toReturn.add(new SelectItem(ver, ver.versaoLabel()));
            }
        }
        return toReturn;
    }

    /**
     * Retorna todas as versões filhas das certificações passadas.
     * Limitando o tipo da versão, isMother ou não.
     * @param certificacoes
     * @param isMother
     * @return 
     */
    public List<SelectItem> getVersoes(List<Certificacao> certificacoes, boolean isMother) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Certificacao cert : certificacoes) {
            for (Versao ver : versaoBean.buscarTodasVersoesPorTipo(isMother, cert)) {
                toReturn.add(new SelectItem(ver, ver.versaoLabel()));
            }
        }
        return toReturn;
    }

    /**
     * Retorna uma lista numérica com números entre o minRespostas e maxRespostas
     * O mínimo e máximo entram na lista.
     * @param minRespostas
     * @param maxRespostas
     * @return List de SelectItem
     */
    public List<SelectItem> getQuantidade(int minRespostas, int maxRespostas) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (int i = minRespostas; i <= maxRespostas; i++) {
            toReturn.add(new SelectItem(i, i + ""));
        }
        return toReturn;
    }

    /**
     * Converte a enum Linguagem em uma lista de SelectItems
     * @return List de SelectItem
     */
    public List<SelectItem> getLinguagens() {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Linguagem lin : Linguagem.values()) {
            toReturn.add(new SelectItem(lin, lin.getIndioma()));
        }
        return toReturn;
    }

    /**
     * Converte a enum TipoQuestoes em uma lista de SelectItems
     * @return List de SelectItem
     */
    public List<SelectItem> getTipoQuestoes() {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (TipoQuestao tq : TipoQuestao.values()) {
            toReturn.add(new SelectItem(tq, UtilMetodos.getResourceBundle(tq.getLabelTQ(), FacesContext.getCurrentInstance())));
        }
        return toReturn;
    }

    /**
     * Converte a enum TipoProva em uma lista de SelectItems
     * @return List de SelectItem
     */
    public List<SelectItem> getTipoProva() {
        return getTipoProva(new TipoProva[]{});
    }

    public List<SelectItem> getTipoProva(TipoProva... excluir) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (TipoProva tq : TipoProva.values()) {
            if (!verificarTipo(excluir, tq)) {
                toReturn.add(new SelectItem(tq, UtilMetodos.getResourceBundle(tq.getLabelTP(), FacesContext.getCurrentInstance())));
            }
        }
        return toReturn;
    }

    private boolean verificarTipo(TipoProva[] tipo, TipoProva tipoProva) {
        for (TipoProva t : tipo) {
            if (t.equals(tipoProva)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Garante um SelectItem na ordem das respostas
     * pro exigir um TreeSet como parametro.
     * Os caracteres < e > são alterados pelos caracteres de escape!
     * @param respostas
     * @return List de SelectItem
     */
    public List<SelectItem> getRespostasDisponiveis(TreeSet<Resposta> respostas) {
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Resposta resposta : respostas) {
            toReturn.add(new SelectItem(resposta, resposta.getOrdem().toString() + ") " + resposta.getResposta().replace("<", "&lt;").replace(">", "&gt;")));
        }
        return toReturn;
    }

    /**
     * Criado para ser utilizado no shooser 
     * de objetivo certificação nas questões
     * @param like
     * @param certificacao
     * @return Lista com objetivos cadastrados
     */
    public List<String> shooser(String like, Certificacao certificacao) {
        List<String> toloop = new ArrayList<String>();
        toloop.addAll(this.objetivoCertificacaoBean.buscarObjetivosDistintos(like, certificacao));
        Set<String> set = new TreeSet<String>();
        for (String s : toloop) {
            set.add(s.replaceAll("\n", "").replaceAll("\r", ""));
        }
        return new ArrayList<String>(set);
    }

    public List<SelectItem> getVersaoPorTipo(boolean isMother, Certificacao certificacao) {
        List<Versao> versoes = versaoBean.buscarTodasVersoesPorTipo(isMother, certificacao);
        List<SelectItem> toReturn = new ArrayList<SelectItem>();
        for (Versao ver : versoes) {
            toReturn.add(new SelectItem(ver, ver.versaoLabel()));
        }
        return toReturn;
    }
}
